package com.woniu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.entity.SysOperateLog;
import com.woniu.mapper.SysOperateLogMapper;
import com.woniu.service.SysOperateLogService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.List;

/**
 * @Author pml
 * @Date 2025/6/19 15:28
 * @Description TODO
 * 操作日志服务实现类
 * 采用响应式编程包装阻塞的数据库操作
 */
@Service
public class SysOperateLogServiceImpl extends ServiceImpl<SysOperateLogMapper, SysOperateLog> implements SysOperateLogService {

    @Resource
    private SysOperateLogMapper sysOperateLogMapper;

    /**
     * 响应式保存操作日志
     * 使用Mono.fromCallable将同步方法包装为异步操作
     * 指定在boundedElastic调度器执行，避免阻塞Netty事件循环线程
     * boundedElastic专为阻塞操作设计，会动态创建线程池
     */
    @Override
    public Mono<Boolean> saveOperateLog(SysOperateLog operateLog) {
        return Mono.fromCallable(() -> save(operateLog))
                .subscribeOn(Schedulers.boundedElastic());
    }

    /**
     * 批量查询操作日志
     * 直接调用父类方法，保持代码一致性
     * @param logIds 日志ID集合
     * @return 日志列表
     */
    @Override
    public List<SysOperateLog> listByIds(Collection<? extends Serializable> logIds) {
        return super.listByIds(logIds);
    }

    /**
     * 根据用户ID查询操作日志
     * 使用QueryWrapper构建查询条件，按操作时间倒序排列，便于查看最新操作
     * @param userId 用户ID
     * @return 该用户的操作日志列表
     */
    @Override
    public List<SysOperateLog> listByUserId(Integer userId) {
        QueryWrapper<SysOperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId)
                .orderByDesc("operate_time"); // 最新操作记录排在前面
        return sysOperateLogMapper.selectList(queryWrapper);
    }

    /**
     * 根据模块查询操作日志
     * 按模块名称精确匹配，并按操作时间倒序排列
     * @param module 模块名称
     * @return 该模块的操作日志列表
     */
    @Override
    public List<SysOperateLog> listByModule(String module) {
        QueryWrapper<SysOperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("module", module)
                .orderByDesc("operate_time");
        return sysOperateLogMapper.selectList(queryWrapper);
    }

    /**
     * 根据时间范围查询操作日志
     * 使用between条件查询指定时间段内的操作日志
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 时间范围内的操作日志列表
     */
    @Override
    public List<SysOperateLog> listByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        QueryWrapper<SysOperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("operate_time", startTime, endTime)
                .orderByDesc("operate_time");
        return sysOperateLogMapper.selectList(queryWrapper);
    }

    /**
     * 清理过期操作日志
     * 计算过期时间点，删除该时间点之前的所有日志
     * 使用QueryWrapper构建条件，提高代码可读性
     * @param days 保留最近天数
     * @return 清理的记录数
     */
    @Override
    public int cleanExpiredLogs(int days) {
        LocalDateTime expiredTime = LocalDateTime.now().minus(days, ChronoUnit.DAYS);
        QueryWrapper<SysOperateLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("operate_time", expiredTime);
        return sysOperateLogMapper.delete(queryWrapper);
    }
}
